package com.xmgps.bdt.infrastructure.util;

import com.xmgps.bdt.domain.bokun.exception.CmdParseException;
import io.netty.buffer.ByteBuf;

import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * Rdss 协议工具
 * @author wangzezhou
 * @date 2022/5/27
 */
public class RdssUtils {

    private final static int SECONDS_PER_HOUR =  3600;
    private final static double METER_PER_KNOT =  1852.0;
    private final static int YEAR_OFFSET =  2000;

    public static Date readDate(ByteBuf in){

        Calendar calendar = Calendar.getInstance();
        calendar.set((int)in.readUnsignedByte() + YEAR_OFFSET,
                in.readUnsignedByte()-1,
                in.readUnsignedByte(),
                in.readUnsignedByte(),
                in.readUnsignedByte(),
                in.readUnsignedByte());

        return calendar.getTime();
    }

    /***
     * 偏移动缓冲区的读取索引位
     * @param in
     * @param byteNum 正数为前移，负数为后移。
     */
    public static void offsetReaderIndex(ByteBuf in, int byteNum){

        // TODO: 修改成 ByteBuf.skipBytes()
        if (byteNum < 0 && Math.abs(byteNum) > in.readerIndex()){
            // byteNum 为负数时，偏移量不能大于 缓冲读已读的索引值
            throw new CmdParseException("缓冲区偏移量大于已读的索引值");
        }
        else if(byteNum > 0 && byteNum > in.readableBytes()){
            // byteNum 为正数时，偏移量不能大于 缓冲可读字节数
            throw new CmdParseException("缓冲区偏移量大于可读字节数");
        }

        in.readerIndex(in.readerIndex() + byteNum);
    }

    public static int readAddress(ByteBuf in){
        // 使用 0xFF 与 byte进行计算后，得到正整数再进行位移计算。否则位移会进行算术计算，导至负值状态的 byte 变成
        int address = in.readUnsignedByte() << 16;
        address |= in.readUnsignedByte() <<8;
        address |= in.readUnsignedByte();
        return address;
    }

    /**
     * RDSS 的速度单位 0.1米/秒 转成 节
     * @param decimetrePerSeconds
     * @return
     */
    public static Double convertSpeedToKnots(Short decimetrePerSeconds){

        if (Objects.isNull(decimetrePerSeconds) || decimetrePerSeconds == 0){
            return 0.0;
        }

        return (decimetrePerSeconds * SECONDS_PER_HOUR)/METER_PER_KNOT;
    }
}
